#include "LookAt.h"

LookAtCamera::LookAtCamera()
: BaseCamera(),
m_v3Target(Vector3(0.0f, 0.0f, 0.0f)), m_v3Up(Vector3(0.0f, 1.0f, 0.0f))
{

}

LookAtCamera::~LookAtCamera()
{

}

__VOID LookAtCamera::SetTarget(__FLOAT x, __FLOAT y, __FLOAT z)
{
	m_v3Target = Vector3(x, y, z);
}

__VOID LookAtCamera::SetUp(__FLOAT x, __FLOAT y, __FLOAT z)
{
	m_v3Up = Vector3(x, y, z);
}

Matrix LookAtCamera::GetViewMatrix()
{
	Matrix InverseTranslate = InverseTranslate.SetIdentity().SetTranslation(-m_v3Position);
	Vector3 zaxis = (m_v3Position - m_v3Target).Normalize();
	Vector3 xaxis = (m_v3Up.Cross(zaxis)).Normalize();
	Vector3 yaxis = (zaxis.Cross(xaxis)).Normalize();

	Matrix Rotate = Rotate.SetIdentity();
	Rotate.m[0][0] = xaxis.x;
	Rotate.m[0][1] = xaxis.y;
	Rotate.m[0][2] = xaxis.z;
	Rotate.m[0][3] = 0;

	Rotate.m[1][0] = yaxis.x;
	Rotate.m[1][1] = yaxis.y;
	Rotate.m[1][2] = yaxis.z;
	Rotate.m[1][3] = 0;

	Rotate.m[2][0] = zaxis.x;
	Rotate.m[2][1] = zaxis.y;
	Rotate.m[2][2] = zaxis.z;
	Rotate.m[2][3] = 0;

	Matrix InverseRotate = Rotate.Transpose();	//R^-1 == R^T

	return InverseTranslate*InverseRotate;
}

Matrix LookAtCamera::GetModelMatrix()
{
	Matrix world;
	Matrix Translate = Translate.SetIdentity().SetTranslation(m_v3Position);
	Vector3 zaxis = (m_v3Position - m_v3Target).Normalize();
	Vector3 xaxis = (m_v3Up.Cross(zaxis)).Normalize();
	Vector3 yaxis = (zaxis.Cross(xaxis)).Normalize();

	Matrix Rotate = Rotate.SetIdentity();
	Rotate.m[0][0] = xaxis.x;
	Rotate.m[0][1] = xaxis.y;
	Rotate.m[0][2] = xaxis.z;
	Rotate.m[0][3] = 0;

	Rotate.m[1][0] = yaxis.x;
	Rotate.m[1][1] = yaxis.y;
	Rotate.m[1][2] = yaxis.z;
	Rotate.m[1][3] = 0;

	Rotate.m[2][0] = zaxis.x;
	Rotate.m[2][1] = zaxis.y;
	Rotate.m[2][2] = zaxis.z;
	Rotate.m[2][3] = 0;
	world = Rotate*Translate;
	return world;
}

void LookAtCamera::MoveForward(float offset)
{
	Vector3 deltaMove = -(m_v3Position - m_v3Target).Normalize()*offset;
	m_v3Position += deltaMove;
	m_v3Target += deltaMove;
}



void LookAtCamera::MoveBackward(float offset)
{
	Vector3 deltaMove = (m_v3Position - m_v3Target).Normalize()*offset;
	m_v3Position += deltaMove;
	m_v3Target += deltaMove;
}

void LookAtCamera::MoveLeft(float offset)
{
	Vector3 zAxis = (m_v3Position - m_v3Target).Normalize();
	Vector3 deltaMove = -(m_v3Up.Cross(zAxis)).Normalize()*offset;
	m_v3Position += deltaMove;
	m_v3Target += deltaMove;
}

void LookAtCamera::MoveRight(float offset)
{
	Vector3 zAxis = (m_v3Position - m_v3Target).Normalize();
	Vector3 deltaMove = (m_v3Up.Cross(zAxis)).Normalize()*offset;
	m_v3Position += deltaMove;
	m_v3Target += deltaMove;
}


void LookAtCamera::RotateUp(float offset)
{
	m_fRotX += offset;
	//if (rotX>3.14f/2)
	//{
	//	//rotX=-3.14f/2;
	//	return;
	//}
	Vector4 localTarget = Vector4(0, 0, -(m_v3Position - m_v3Target).Length(), 1);
	Matrix RotateAroundX = RotateAroundX.SetIdentity().SetRotationX(offset);
	Vector4 localNewTarget = localTarget*RotateAroundX;
	Vector4 newTarget = localNewTarget*GetModelMatrix();
	m_v3Target = Vector3(newTarget.x, newTarget.y, newTarget.z);
}

void LookAtCamera::RotateDown(float offset)
{
	/**/
	m_fRotX -= offset;
	//if (rotX<3.14f/2)
	//{
	//	//rotX=3.14f/2;
	//	return;
	//}
	Vector4 localTarget = Vector4(0, 0, -(m_v3Position - m_v3Target).Length(), 1);
	Matrix RotateAroundX = RotateAroundX.SetIdentity().SetRotationX(-offset);
	Vector4 localNewTarget = localTarget*RotateAroundX;
	Vector4 newTarget = localNewTarget*GetModelMatrix();
	m_v3Target = Vector3(newTarget.x, newTarget.y, newTarget.z);
}

void LookAtCamera::RotateLeft(float offset)
{
	Vector4 localTarget = Vector4(0, 0, -(m_v3Position - m_v3Target).Length(), 1);
	Matrix RotateAroundY = RotateAroundY.SetIdentity().SetRotationY(offset);
	Vector4 localNewTarget = localTarget*RotateAroundY;
	Matrix world = world.SetIdentity();
	Vector4 newTarget = localNewTarget*GetModelMatrix();
	m_v3Target = Vector3(newTarget.x, newTarget.y, newTarget.z);
}

void LookAtCamera::RotateRight(float offset)
{
	Vector4 localTarget = Vector4(0, 0, -(m_v3Position - m_v3Target).Length(), 1);
	Matrix RotateAroundY = RotateAroundY.SetRotationY(-offset);
	Vector4 localNewTarget = localTarget*RotateAroundY;
	Matrix world = world.SetIdentity();
	Vector4 newTarget = localNewTarget*GetModelMatrix();
	m_v3Target = Vector3(newTarget.x, newTarget.y, newTarget.z);
}